package com.excilys.formation.project.entities;

import java.io.Serializable;
import java.util.Set;

import javax.persistence.Entity;
import javax.persistence.FetchType;
import javax.persistence.GeneratedValue;
import javax.persistence.GenerationType;
import javax.persistence.Id;
import javax.persistence.ManyToOne;
import javax.persistence.OneToMany;
import javax.persistence.Table;
import javax.persistence.UniqueConstraint;

import org.hibernate.validator.constraints.Length;

/**
 * Compte est la classe de lien avec la table compte en base pour l'ORM.
 * 
 * @author excilys
 */
@SuppressWarnings("serial")
@Entity
@Table(uniqueConstraints = { @UniqueConstraint(columnNames = { "numero" }) })
public class Compte implements Comparable<Compte>, Serializable {

    /**
     * Clef primaire du compte.
     */
    private long id;

    /**
     * Type de compte
     */
    private TypeCompte typeCompte;

    /**
     * Clef primaire du compte.
     */
    private String numero;

    /**
     * Solde du compte.
     */
    private double solde;

    /**
     * Client a qui appartient le compte.
     */
    private Client client;

    /**
     * Opérations sur ce compte.
     */
    private Set<Operation> operations;

    /**
     * Taille d'un numéro de compte en france.
     */
    public static final int TAILLE_NUMERO = 23;

    /**
     * Renvoie le numéro de compte. Taille égale à {@value #TAILLE_NUMERO}
     * 
     * @return numéro
     */
    @Length(max = TAILLE_NUMERO, min = TAILLE_NUMERO)
    public String getNumero() {
        return numero;
    }

    /**
     * Change le numéro de compte. Taille égale à {@value #TAILLE_NUMERO}
     * 
     * @param numero
     *            Le nouveau numéro de compte
     */
    public void setNumero(String numero) {
        this.numero = numero;
    }

    /**
     * Renvoie le solde du compte.
     * 
     * @return solde
     */
    public double getSolde() {
        return solde;
    }

    /**
     * Change le solde du compte.
     * 
     * @param solde
     *            Le nouveau solde
     */
    public void setSolde(double solde) {
        this.solde = solde;
    }

    /**
     * Renvoie le client titulaire du compte.
     * 
     * @return client
     */
    @ManyToOne(optional = false)
    public Client getClient() {
        return client;
    }

    /**
     * Change le client titulaire du compte.
     * 
     * @param client
     *            le nouveau client titulaire du compte.
     */
    public void setClient(Client client) {
        this.client = client;
    }

    /**
     * @return Les opérations associées au compte
     */
    @OneToMany(mappedBy = "compte", fetch = FetchType.LAZY)
    public Set<Operation> getOperations() {
        return operations;
    }

    /**
     * Change l'emsemble des opérations associées au compte.
     * 
     * @param operations
     *            La nouvelle liste des opérations
     */
    public void setOperations(Set<Operation> operations) {
        this.operations = operations;
    }

    @Override
    public String toString() {
        return String.valueOf(numero);
    }

    @Override
    public int compareTo(Compte compte) {
        return this.getNumero().compareTo(compte.getNumero());
    }

    /**
     * Renvoie la clef primaire Change la clef primaire (auto générée).
     * 
     * @return id
     */
    @Id
    @GeneratedValue(strategy = GenerationType.IDENTITY)
    public long getId() {
        return id;
    }

    /**
     * Change la clef primaire (auto générée).
     * 
     * @param id
     *            Clef primaire du client.
     */
    public void setId(long id) {
        this.id = id;
    }

    @ManyToOne(optional = false)
    public TypeCompte getTypeCompte() {
        return typeCompte;
    }

    public void setTypeCompte(TypeCompte typeCompte) {
        this.typeCompte = typeCompte;
    }

}
